/** proxy **/

class Tvue{
    constructor(options) {
        console.log('options', options);
        this.$options = options;
        this._data = options.data;
        this.observe(this.$options.data);
        this.compile();
    }

    // 观察、劫持、监听
    observe(data) {
        let temp = {};
        this._data = new Proxy(data, {
            get(target, key) {
                console.log(`${key} get`);
                temp[key] = new Dep();
                if (Dep.target) {
                    temp[key].addSub(Dep.target);
                }
                return Reflect.get(target, key);
            },
            set(target, key, newValue) {
                console.log(`${key} set`);
                temp[key].notify(newValue);
                return Reflect.set(target, key, newValue);
            }
        })
    }

    compile() {
        let ele = document.querySelector(this.$options.el);
        this.compileNodes(ele);
    }

    compileNodes(ele) {
        const childNodes = ele.childNodes;
        childNodes.forEach(node => {
            if (node.nodeType === 1) {
                // 查找指令
                let attrs = node.attributes;
                console.log('attrs', attrs);
                [...attrs].forEach(attr => {
                    let attrName = attr.name;
                    let attrValue = attr.value;
                    if (attrName === 'v-modal') {
                        node.value = this._data[attrValue];
                        node.addEventListener('input', (e) => {
                            console.log(e.target.value);
                            this._data[attrValue] = e.target.value;
                        })
                    }

                    if (attrName === "v-text") {
                        node.innerText = this._data[attrValue];
                        new Watcher(this._data, attrValue,(newValue) => {
                            node.innerText = newValue;
                        })
                    }

                    if (attrName === "v-html") {
                        node.innerHTML = this._data[attrValue];
                        new Watcher(this._data, attrValue,(newValue) => {
                            node.innerHTML = newValue;
                        })
                    }
                })

                // 元素节点
                if (node.childNodes.length > 0) {
                    this.compileNodes(node);
                }
            } else if (node.nodeType === 3) {
                // 文本节点
                let reg = /\{\{\s*([^{}\s]+)\s*\}\}/g;
                let textContent = node.textContent;
                if (reg.test(textContent)) {
                    let $1 = RegExp.$1;
                    node.textContent = node.textContent.replace(reg, this._data[$1]);

                    new Watcher(this._data, $1,(newValue) => {
                        console.log('视图更新！');
                        let oldValue = this._data[$1];
                        node.textContent = node.textContent.replace(oldValue, newValue);
                    })
                }
            }
        })
    }
}

class Dep {
    constructor() {
        this.subs = [];
    }

    addSub(sub) {
        this.subs.push(sub);
    }

    notify(newValue) {
        this.subs.forEach(sub => {
            sub.update(newValue);
        })
    }
}

class Watcher {
    constructor(data, key, cb) {
        Dep.target = this;
        data[key];  // 触发get 收集watcher
        this.cb = cb;
        // Dep.target = null;
    }

    update(newValue) {
        this.cb(newValue);
    }
}